import create
import time #Used to sleep functions to prevent overloading robot
import sys #Used for system functions
import socket

class sumoBot:

    def __init__(self):
        self.robot = create.Create(3)
        self.robot.toFullMode()

        #Robot's Attributes
        self.health = 100
        self.alive = True        
        self.amAttacking = False
        self.outOfBounds = False

        #Remote Controller Functions
        self.FORWARD = 130
        self.TURN_LEFT = 129
        self.TURN_RIGHT = 131
        self.ATTACK = 136
        self.CLOSE = 138
        
        #Set up Client information
        ## Note about this section:
        ## This creates a client socket, meaning it needs to directly connect to a server
        ## socket in order to work.
        self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)        
        self.client_socket.connect(("192.168.1.10", 5000)) #connects to the server / other robot
        self.client_socket.setblocking(0) #This means the socket will expect data when recv is called


    #Tells sumoBot to attack!
    def attemptAttack(self):
        self.amAttacking = True
        self.robot.go(45)

    #Sumo was attacked while he was attacking!
    def beAttackedHalf(self, dmg, modifier):
        self.beAttacked(dmg*modifier)

    #Sumo was attacked 
    def beAttacked(self, dmg):
        self.health = self.health - dmg
        self.checkHealth()

    #Checks Health Status
    def checkHealth(self):
        if self.health <= 0: #Checks to see if he should be dead
            self.alive = False
        print self.health #Debugging Purposes
            
    #Performs robot.close() function
    def close(self):
        self.client_socket.send("I Died")
        self.robot.close()
        self.client_socket.close()
        sys.exit("Quit")
        
    #Determines if sumoBot is alive   
    def isAlive(self):
        return self.alive

    #Checks server to determine if Sumo has received an attack call
    def receiveAttack (self, var):
        if var > 0 :
            return True
        else:
            return False

    #Sends attack info to the other bot
    def sendAttack(self, dmg):
        self.client_socket.send(str(dmg))
        self.amAttacking = False      

    #Remote Control Listener - waits for commands from user
    def waitForCommand(self):        
        sensor = self.robot.sensors([create.INFRARED_BYTE])
            
        #Movement Commands
        if sensor[create.INFRARED_BYTE] == self.FORWARD and self.amAttacking == False and self.outOfBounds == False:
            self.robot.go(30)
        elif sensor[create.INFRARED_BYTE] == self.TURN_LEFT and self.amAttacking == False:
            self.robot.go(0,180)
        elif sensor[create.INFRARED_BYTE] == self.TURN_RIGHT and self.amAttacking == False:
            self.robot.go(0,-180)
        
        #Attack Command - Sumo may attack as long as his current action isn't to attack
        elif sensor[create.INFRARED_BYTE] == self.ATTACK and self.amAttacking == False and self.outOfBounds == False:
            self.attemptAttack()
            
        #Exit Program - For Debugging Purposes
        elif sensor[create.INFRARED_BYTE] == self.CLOSE:
            self.close()

        #Ensures Sumo will continue moving forward if he's attacking
        elif self.amAttacking == True:
            if self.outOfBounds == False:
                self.robot.go(50)
            else:
                self.amAttacking = False
        elif self.amAttacking == False:
            self.robot.go(0,0)        

    #Environment Listener - waits for bumper action
    def waitForEnvironment(self):
        sensor = self.robot.sensors([create.LEFT_BUMP, create.RIGHT_BUMP, create.CLIFF_FRONT_LEFT_SIGNAL, create.CLIFF_FRONT_RIGHT_SIGNAL])
        #This allows Sumo to continuously ask for new server requests when there aren't any to receive
        # It helps Sumo not have to wait on data to be transmitted, so Sumo can continue running
        
        #Bumper Was Pressed
        if sensor[create.LEFT_BUMP] == 1 or sensor[create.RIGHT_BUMP] == 1:
            try:
                data = int(self.client_socket.recv( 512 ))
            except:
                data = -1 #arbitrary number to imply no data was sent through
                sys.exc_clear() #clears exceptions that are brought up because of the socket being non-blocking       
            if self.receiveAttack(int(data)) == False:#If Sumo didn't receive an attack, then he must be attacking!
                if self.amAttacking == True: 
                    self.sendAttack(20)
            else:#Sumo probably received an attack
                if self.amAttacking == True: #if Sumo is attacking, split damage
                    self.beAttackedHalf(int(data), 0.5)
                else:#Sumo was attacked
                    self.beAttacked(data)
        #Going out of bounds
        if sensor[create.CLIFF_FRONT_RIGHT_SIGNAL] > 1195 or sensor[create.CLIFF_FRONT_LEFT_SIGNAL] > 1100:
            self.outOfBounds = True
            print "right sensors ",sensor[create.CLIFF_FRONT_RIGHT_SIGNAL]," left sensor ", sensor[create.CLIFF_FRONT_LEFT_SIGNAL]
        else:
            self.outOfBounds = False
            print "right sensors ",sensor[create.CLIFF_FRONT_RIGHT_SIGNAL]," left sensor ", sensor[create.CLIFF_FRONT_LEFT_SIGNAL]

bot = sumoBot()
while bot.isAlive():
    bot.waitForEnvironment()
    bot.waitForCommand()
    time.sleep(0.1)
bot.close()
sys.exit("Died")
